---
title: Autocomplete
description: An Autocomplete is a component that allows for real-time suggestions from a pre-determined list as the user types by filtering data based on the current value. It can also be used to interact with an API that handles the sorting, filtering, matching, etc as well.
docType: Demo
docGroup: Components
group: Inputs
keywords: [form]
alias: [AutoComplete, Select, Typeahead, Listbox]
hooks: [useAutocomplete]
components:
  [
    Autocomplete,
    AutocompleteClearButton,
    AutocompleteDropdownButton,
    AutocompleteCircularProgress,
  ]
---

# Autocomplete

An `Autocomplete` is a component that allows for real-time suggestions from a
pre-determined list as the user types by filtering data based on the current
value. It can also be used to interact with an API that handles the sorting,
filtering, matching, etc as well.

## Simple Example

An `Autocomplete` requires a list of options which can be strings or an object
with a `label` or `name` string so that the options can be filtered as the user
types. In addition, a `listboxLabel` or `listboxLabelledby` prop must be
defined for accessibility to provide a label for the listbox.

```demo source="./SimpleExample.tsx"

```

### Simple Label Example

This is the same example as above, but using options as `{ label: string }`.

```demo source="./SimpleLabelExample.tsx"

```

## Object Options

The `Autocomplete` can support any object option by also providing an
`getOptionLabel` prop that will return a string value for each option.

> !Info! See [Typescript Typing](#typescript-typing) for type behavior.

```demo source="./ObjectOptionsExample.tsx"

```

## Option Props

The `Autocomplete` will automatically pass through common `Option` props that
exist on each option.

```demo source="./OptionPropsExample.tsx"

```

### Get Option Props

Another way to pass props to each option is using the `getOptionProps` function.

```demo source="./GetOptionPropsExample.tsx"

```

### Disabled Options

An option can be disabled by adding `disabled: true` to the option or using `getOptionProps`
to return `disabled: true`.

```demo source="./DisabledOptionsExample.tsx"

```

## Controlling the Value

If the current value is needed, provide a `value` and `setValue` prop.

```demo source="./ControllingTheValueExample.tsx"

```

### Setting a default value

If the value does not need to be controlled but one of the options should
be selected by default, set the `defaultValue` prop instead.

> !Info! See [Typescript Typing](#typescript-typing) for type behavior.

```demo source="./SettingADefaultValueExample.tsx"

```

### Getting the current value

> !Warn! It is recommended to control the `value` instead of using this option.

When the `value` does not need to be stored anywhere but can be used for other
actions, the `onValueChange` prop can be used.

```demo source="./GettingTheCurrentValueExample.tsx"

```

### Controlling the input value

If the input value needs to be controlled, provide a `query` and `setQuery` prop.

```demo source="./ControllingTheInputValueExample.tsx"

```

### Getting the current input value

If the input value doesn't need to be controlled, the value can be retrieved
with the normal `onChange` event handler.

```demo source="./GettingTheCurrentInputValueExample.tsx"

```

## Disable Filtering

There are some cases where the available options should only be suggestions and
not required value such as displaying the most recent searches. Set the `filter`
prop to `noopAutocompleteFilter` to enable this behavior which also enables the
`allowAnyValue` prop.

> !Info! This is the default behavior when `type="search"` is set.

```demo source="./DisableFilteringExample.tsx"

```

### Custom Filter Function

The `Autocomplete` uses the
[caseInsensitiveSearch](/utils/case-insensitive-search) filter function by
default but can be changed using the `filter` prop. The filter function must
return the filtered list and is called with an object containing:

- `list` - The list of `options` to filter
- `query` - The current text field value
- `extractor` - The `extractor` function to get a string for each option

This example will show how the filter function could be swapped out for the
[fuzzySearch](/utils/fuzzy-search).

```demo source="./CustomFilterFunctionExample.tsx"

```

## Allow Any Value

The `Autocomplete` normally behave like a searchable select component where it
requires a specific option to be selected and will reject all other values. If
any value should be allowed, enable the `allowAnyValue` prop.

```demo source="./AllowAnyValueExample.tsx"

```

### Creatable

An alternative to the `allowAnyValue` prop is to allow the user to create a new
option with their typed value by manually selecting the dynamically generated
option. There is nothing built-in to the `Autocomplete` component itself, but
can be easily coded with a few changes:

- ensure the provided `options` are a list of objects
- provide a custom `filter` function that inserts a new option at the end (or
  beginning) of the filtered items
- optionally: also provide a custom `getOptionLabel` function to handle the
  creatable item

This example will show how to insert a `Add: "${query}"` option with the list of
fruits. The `Add: "${query}"` is set as the `children` so that when the option
is selected, only the `query` will be inserted into the input.

```demo source="./CreatableAutocompleteExample.tsx"

```

## Async Example

The `Autocomplete` supports rendering a `CircularProgress` after the input field to show
async behavior. The `CircularProgress` will be shown while the `loading` prop is true.

This example below will "load" the options each time the autocomplete is opened.

```demo source="./AsyncExample.tsx"

```

### Debounced Search Example

When the `Autocomplete` should be used as a `<input type="search" />` to send
requests to an API as the user types to get the options, set the `type="search"`
and add a custom `onChange` handler to send the current value to the search API.
It is recommended to either debounce or throttle these search requests so that
each keystroke is not a new request.

`react-md` provides two hooks to help with debouncing and throttling:

- [useDebouncedFunction](/hooks/use-debounced-function)
- [useThrottledFunction](/hooks/use-throttled-function)

This example will show a debounced implementation while the next example will
show a throttled implementation.

```demo source="./DebouncedSearchExample.tsx"

```

### Throttled Search Example

This is the same example as above, but using [useThrottledFunction](/hooks/use-throttled-function)
instead.

```demo source="./ThrottledSearchExample.tsx"

```

## Multiple Values

The `Autocomplete` supports multiple values by either:

- setting the `defaultValue` to a list
- controlling the `value` and setting it to a list

When multiple values are allowed, the `Autocomplete` will display inline chips
representing all the selected values and automatically clear the input when a
new option is selected.

```demo source="./MultipleValuesExample.tsx"

```

### Disable Close On Select

To prevent the listbox from closing when an option is selected, enable the
`disableCloseOnSelect` prop.

> !Success! This is also supported for the single select `Autocomplete`

```demo source="./DisableCloseOnSelectExample.tsx"

```

### Checkboxes

The multiselect `Autocomplete` also supports updating all the options to use
checkbox icons by enabling the `checkboxes` prop. This also enables the
`disableCloseOnSelect` by default.

The `Option` will use the `ICON_CONFIG.checkbox` and
`ICON_CONFIG.checkboxChecked` icons for the unselected and selected states.

> !Info! These icons can be overridden using the `getOptionProps` and returning
> a custom `selectedIcon` / `unselectedIcon`.

```demo source="./MultiselectCheckboxesExample.tsx"

```

### Disable Inline Chips

If the selected options should not be shown as inline chips, enable the
`disableInlineChips` prop.

```demo source="./DisableInlineChipsExample.tsx"

```

### Filter Selected

The selected options can also be removed from the listbox by enabling the
`filterSelected` prop. It is only recommended to enable this prop when the
`disableInlineChips` is enabled.

```demo source="./FilterSelectedExample.tsx"

```

### Customizing Inline Chips

The inline chips can be customized using the `getChipProps` which provides the
`index` and `option` being rendered. This can be used to disable chips, add
custom styles, change the theme, etc.

```demo source="./CustomizingInlineChipsExample.tsx"

```

## Customization

### Highlights

The search query can be highlighted using the
[HighlightText](/components/highlight-text) component and the `getOptionProps`
to provide highlighted `children` to each option.

```demo source="./HighlightsExample.tsx"

```

### Disabling the Clear and Dropdown Buttons

The clear button and dropdown button can be removed by enabling the
`disableClearButton` and `disableDropdownButton` props respectively. They do not
need to be used in tandem.

> !Success! The keyboard shortcuts for clearing the input and showing/hiding the
> menu will still be enabled if these props are enabled.

```demo source="./DisablingTheClearAndDropdownButtonsExample.tsx"

```

### Github's Label Picker

> !Warn! This is a more complex example that will showcase most of the
> customization options available in the `Autocomplete` component and other
> child components.

This demo shows how the Github label picker could be created with `react-md`
with most of the same behavior. Here's a breakdown of how this was created:

- Start by creating a simple `Button` + `FixedDialog` combination to display the
  `Autocomplete`
- Create a multiselect `Autocomplete` with most of the default UI disabled to
  better match Github
  - `disableClearButton`
  - `disableDropdownButton`
  - `disableInlineChips`
  - `listboxProps.disableElevation`
- Update the `Autocomplete` so that the listbox renders inline with the other
  content and within the dialog
  - `listboxProps.disablePortal`
  - `listboxProps.disableFixedPositioning`
- Ensure the listbox is always visible by enabling the `visible` prop and
  providing a noop for the `setVisible` prop. Also enable the
  `disableCloseOnSelect` prop to ensure items are still filtered after selecting
  an new value
- Set `updateQueryOnSelect` to `"as-is"` so that selecting a new value doesn't
  change the value in the `Autocomplete`
- Update the behavior so that the selected values are only updated when the
  dialog closes by:
  - creating a `nextValue` ref that is mutated with the `onValueChange` prop
  - setting the `defaultValue` to the `labels` state which ensures the latest
    values are selected each time the dialog is opened
  - add an `onExited` handler to the `Dialog` that sets the state with the
    `nextValue` ref
- Allow filtering to happen anywhere within the label name by setting
  `filter={(options) => caseInsensitiveSearch(options)}`
- Sort the `options` prop for the `Autocomplete` so that the selected labels
  appear first
- Provide a `onKeyDown` handler for the `Dialog`, `Listbox`, and `input` that
  closes the dialog when the `Escape` key is pressed
- Render the selected labels in a `Box` with `Chip` components
- Update any styles to match Github

```demo source="./GithubLabelPickerExample.tsx"

```

## Typescript Typing

The `Autocomplete` option is defined as:

```ts disableTransform
type AutomaticTextExtraction = string | { label: string } | { name: string };
type AutocompleteOption = AutomaticTextExtraction | object;
```

Each option should extend this type and will automatically be inferred for
almost all use cases.

```tsx disableTransform
// ✅ Inferred as `string[]`
<Autocomplete {...props} options={["One", "Two", "Three"]} />;

// ✅ Inferred as `string[]`
const options = ["One", "Two", "Three"];
<Autocomplete {...props} options={options} />;

// ✅ Inferred as `("One" | "Two" | "Three")[]`
const options = ["One", "Two", "Three"] as const;
<Autocomplete {...props} options={options} />;

// ✅ Inferred as `{ name: string, value: number }`
const options = [
  { name: "Hello", value: 1 },
  { name: "World", value: 2 },
];
<Autocomplete
  {...props}
  options={options}
/>;

// ✅ Inferred as `State`
interface State {
  name: string;
  abbreviation: string;
}
const options: readonly State[] = [
  { name: "Virginia", abbreviation: "VA" },
  { name: "Whyoming", abbreviation: "WY" },
];
<Autocomplete
  {...props}
  options={options}
/>;
```

The only time it appears to have an issue is when the list of options are
defined with `as const`:

```tsx disableTransform
const options = [
  { fullName: "Virginia", abbreviation: "VA" },
  { fullName: "Whyoming", abbreviation: "WY" },
] as const;
<Autocomplete
  {...props}
  options={options}
  // ❌ Parameter 'state' implicity has an `any` type.
  getOptionLabel={(state) => state.fullName}
/>;
```

The type issue can be resolved by one of the following:

```tsx disableTransform
const options = [
  { fullName: "Virginia", abbreviation: "VA" },
  { fullName: "Whyoming", abbreviation: "WY" },
] as const;

type State = (typeof options)[number];

// 1. Provide the type definition to the `getOptionLabel` parameter
<Autocomplete
  {...props}
  // ✅ `state` and `options` are set to the `State` type
  options={options}
  getOptionLabel={(state: State) => state.fullName}
/>;

// 2. Provide the type definition as the `Autocomplete` type parameter
<Autocomplete<State>
  {...props}
  // ✅ `state` and `options` are set to the `State` type
  options={options}
  getOptionLabel={(state) => state.fullName}
/>;
```

## Accessibility

The `Autocomplete` component implements the
[combobox](https:://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant)
so the `<input />` will remain focused while the options gain styles to show
they are focused.

### Labels

- The listbox requires an `aria-label`/`aria-labelledby` by the
  `listboxLabel`/`listboxLabelledby` props respectively
- The dropdown button defaults to an `aria-label`/`aria-labelledby` based on the
  `listboxLabel`/`listboxLabelledby` props respectively
- The inline circular progress bar defaults to an `aria-label="Loading"`

### Keyboard Movement

The following keyboard movement has been implemented:

#### Closed Listbox

- Typing will open the listbox and keep focus on the input.
- `ArrowDown` - Opens the listbox and focuses the first option.
- `Alt+ArrowDown` - Opens the listbox and keeps focus on the input.
- `ArrowUp` - Opens the listbox and focuses the last option.
- `Escape` - Clears the value.
- `Home`/`End` - Moves cursor to the start and end of the input

#### Open Listbox

- Typing will move focus back to the input
- `ArrowDown` - Moves focus to the next option in the listbox. If focus was on
  the input, the first option will be focused.
- `ArrowUp` - Moves focus to the previous option in the listbox. If focus was on
  the input, the last option will be focused.
- `Alt+ArrowUp` - If an option is focused, moves focus into the input. If the
  input is focused, closes the listbox.
- `ArrowLeft`/`ArrowRight`/`Home`/`End` - Moves focus into the input and uses
  default text editing behavior for these keys.
- `Escape` - Hides the listbox.
